package crud.controller;

import java.nio.charset.Charset;
import java.util.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import apijson.JSON;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;

import com.alibaba.fastjson.serializer.SerializerFeature;
import crud.domain.CrudResult;
import crud.domain.SysInterface;
import crud.domain.SysVerify;
import crud.service.SQLCrudService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import lombok.extern.slf4j.Slf4j;

import apijson.RequestMethod;
import apijson.framework.APIJSONController;
import apijson.orm.Parser;

import crud.service.JSONCrudService;
import crud.service.VerifyService;
import crud.verify.ParamVerify;
import crud.service.InterfaceService;

@Slf4j
@RestController
@RequestMapping("")
public class CRUDController extends APIJSONController<Long> {

    @Autowired
    HttpServletRequest request;

    @Autowired
    HttpServletResponse response;

    @Resource
    private InterfaceService interfaceService;

    @Resource
    private VerifyService verifyService;

    @Resource
    private JSONCrudService jsonCrudService;

    @Resource
    private SQLCrudService sqlCrudService;


    @Override
    public Parser<Long> newParser(HttpSession session, RequestMethod method) {
        return super.newParser(session, method).setNeedVerify(false);
    }

    private JSONObject doCrud(JSONObject reqBody) {
        JSONObject resBody = new JSONObject();
        try {
            //接口定义
            SysInterface sysInterface = interfaceService.getInterface(request.getRequestURI());

            //log.info(String.format("[%s]模板[%s]", sysInterface.getApiType(), sysInterface.getApiTemplate()));

            //参数校验
            List<SysVerify> sysVerifyList = verifyService.getVerify(sysInterface.getId());
            ParamVerify.doVerify(reqBody, sysVerifyList);

            //执行数据库操作
            String apiType = sysInterface.getApiType();
            if (Objects.equals(apiType, "JSON")) {
                CrudResult crudResult = jsonCrudService.doCrud(reqBody, sysInterface, this);
                resBody.put("status", crudResult.getStatus());
                resBody.put("message", crudResult.getMessage());
                resBody.put("data", crudResult.getData());
            } else if (Objects.equals(apiType, "SQL")) {
                CrudResult crudResult = sqlCrudService.doCrud(reqBody, sysInterface);
                resBody.put("status", crudResult.getStatus());
                resBody.put("message", crudResult.getMessage());
                resBody.put("data", crudResult.getData());
            } else {
                resBody.put("status", 1);
                resBody.put("message", String.format("[%s]模板暂未支持", apiType));
                resBody.put("data", new JSONObject());
            }
        } catch (Exception ex) {
            log.error(ex.getMessage());
            resBody.put("status", 1);
            resBody.put("message", ex.getMessage());
            resBody.put("data", new JSONObject());
        }

        return resBody;
    }

    @PostMapping("/**")
    public void doPost(@RequestBody JSONObject reqBody) {
        log.info("请求方法[POST],请求URI[{}],请求参数[{}]", request.getRequestURI(), reqBody.toJSONString());
        JSONObject data = doCrud(reqBody);
        response.setStatus(200);
        ServletUtil.write(response, JSON.toJSONString(data, SerializerFeature.WriteDateUseDateFormat), "application/json");
    }

    @GetMapping("/**")
    public void doGet() {
        java.util.Map<java.lang.String, java.lang.String> reqParam = HttpUtil.decodeParamMap(request.getQueryString(), Charset.defaultCharset());
        log.info("请求方法[GET],请求URI[{}],请求参数[{}]", request.getRequestURI(), reqParam);
        JSONObject data = doCrud((JSONObject) JSONObject.toJSON(reqParam));
        response.setStatus(200);
        ServletUtil.write(response, JSON.toJSONString(data, SerializerFeature.WriteDateUseDateFormat), "application/json");
    }
}
